home *** CD-ROM | disk | FTP | other *** search
/ Delphi 2 - Developers' Solutions / Delphi 2 Developers' Solutions.iso / dds / chap02 / howto01 / drwsutl2.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-03-05  |  41.8 KB  |  1,167 lines

  1. unit Drwsutl2;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  7.   Forms, Dialogs, StdCtrls, Buttons, ExtCtrls, ShellAPI, FileCtrl ;
  8.  
  9. type
  10.   TFileWorkBench = class( TComponent )
  11.   public
  12.     GlobalError        : Integer;  { This is used by FMXUCopyFile for er code }
  13.     GlobalErrorType    : Integer;  { This holds the Operation code            }
  14.     function ForceTrailingBackSlash( const TheFileName : String ) : String;
  15.     function StripNonRootTrailingBackSlash(
  16.               const TheFileName : String ) : String;
  17.     procedure GetFileAttributes( TheFile : String; var IsDirectory , IsArchive ,
  18.                 IsVolumeID , IsHidden , IsReadOnly , IsSysFile : Boolean );
  19.     procedure FMXUCopyFile(const FileName, DestName: String);
  20.     function CopyFile( TargetPath ,
  21.                DestinationPath : String ) : Boolean;
  22.     procedure ChangeTheDirectory( NewPath : String );
  23.     procedure ChangeTheDriveAndDirectory( NewDrive : Integer );
  24.     procedure CopyTheFile( OldPath , NewPath : String );
  25.     procedure MoveTheFile( OldPath , NewPath : String );
  26.     procedure DeleteTheFile( ThePath : String );
  27.     procedure RenameTheFile( OldPath , NewName : String );
  28.     procedure CreateNewDirectory( NewPath : String );
  29.     procedure RemoveDirectory( ThePath : String );
  30.   end;
  31.   TFileIconPanel = class( TPanel )
  32.   private
  33.     { Private declarations }
  34.     FHighlightColor : TColor;                 { This holds bright edge bevel }
  35.     FShadowColor    : TColor;                 { This holds dark edge bevel   }
  36.     procedure TheClick( Sender : TObject );   { This holds override click    }
  37.   protected                                   { event method procedure.      }
  38.     { Protected declarations }
  39.     procedure Paint; override;                { This allows custom painting  }
  40.   public
  41.     { Public declarations }
  42.     FTheIcon : TIcon;                         { This is the display icon    }
  43.     FTheName : String;                        { This is the filename        }
  44.     FTheLabel : TLabel;                       { This is the display label   }
  45.     Selected : Boolean;                       { This holds selection status }
  46.     constructor Create(AOwner : TComponent); override; { override create    }
  47.     procedure Initialize( PanelX              ,             { Left          }
  48.                           PanelY              ,             { Top           }
  49.                           PanelWidth          ,             { Width         }
  50.                           PanelHeight         ,             { Height        }
  51.                           PanelBevelWidth     ,             { Bevel Width   }
  52.                           LabelFontSize         : Integer;  { Font size     }
  53.                           PanelColor          ,             { Main color    }
  54.                           PanelHighlightColor ,             { Bright color  }
  55.                           PanelShadowColor    ,             { Dark color    }
  56.                           LabelTextColor        : TColor;   { Text color    }
  57.                           TheFilename         ,             { Filename      }
  58.                           LabelFontName         : String;   { Font name     }
  59.                           LabelFontStyle        : TFontStyles;  { Font style}
  60.                           ExtraData             : Integer       );  { Drive }
  61.     destructor Destroy; override;             { override destroy to free    }
  62.   end;
  63.   TFileIconPanelScrollBox = class( TScrollBox )
  64.   public
  65.     { Public methods and data }
  66.     TheFWB              : TFileWorkBench; { Used for file manipulation         }
  67.     IconsNeedRefreshing : Boolean;                   { Flag to redo display    }
  68.     TheIconSize        : Integer;   { Holds Individual Icon size               }
  69.     TheIconSpacing     : Integer;   { Holds total icon footprint               }
  70.     MaxIconsInARow     : Integer;   { Set for screen size.                     }
  71.     TheStoredHandle    : HWnd;
  72.     procedure Update;                                { Called to reset display }
  73.     constructor Create( AOwner : TComponent ); override;  { Override inherited }
  74.     procedure ClearTheFIPs;                          { Clears the FIPs safely  }
  75.     procedure AddDriveIcons( var XCounter , YCounter : Integer ); { Add drives }
  76.     procedure GetColorsForFileIcon( TheFile : String;
  77.                var BC , HC , SC , TC : TColor );
  78.     procedure GetIconsForEntireDirectory( TargetPath  : String );
  79.     function GetNextSelection( SourceDirectory : String;
  80.               var CurrentItem : Integer ) : String;
  81.   end;
  82.  
  83.   { This procedure spaces out the bitbtn components on a tpanel }
  84.   procedure SpacePanelButtons( WhichPanel : TPanel );
  85.   procedure GetIconForFile( TheName : String; var TheIcon : TIcon );
  86.  
  87. implementation
  88. uses DRWSUTL1;
  89. {$R DRWSUTL2.RES}                 { Import custom resource file }
  90.  
  91. { This procedure gets an icon for a file using FindExecutable  }
  92. { and ExtractIcon. (assumes file/dir is passed)                }
  93. procedure GetIconForFile( TheName : String; var TheIcon : TIcon );
  94. var TheExt           : String; { File extension holder }
  95.     TheOtherPChar  ,           { Windows ASCIIZ string }
  96.     ThePChar         : PChar;  { Windows ASCIIZ string }
  97.     Dummy : Word;
  98. begin
  99.   { Check for directory and if so get directory icon from RES file }
  100.   if (( FileGetAttr( TheName ) and faDirectory ) = faDirectory ) then
  101.   begin
  102.     { Set up the PChar to communicate with Windows }
  103.     GetMem( TheOtherPChar , 255 );
  104.     { Convert Pascal-style string to ASCIIZ Pchar }
  105.     StrPCopy( TheOtherPChar , 'DIRECTORY' );
  106.     { Use API call to return icon handle of Icon Resource in FILECTRL.RES }
  107.     TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  108.     { Release memory from PChar }
  109.     FreeMem( TheOtherPChar , 255 );
  110.     { Leave }
  111.     exit;
  112.   end;
  113.   { Assume archive file; get its extension }
  114.   TheExt := Uppercase( ExtractFileExt( TheName ));
  115.   { If not an executable/image file then use FindExecutable to get icon }
  116.   if (( TheExt <> '.EXE' ) and ( TheExt <> '.BAT' ) and
  117.       ( TheExt <> '.PIF' ) and ( TheExt <> '.COM' )) then
  118.   begin
  119.     { Grab three chunks of memory }
  120.     GetMem( ThePChar , 255 );
  121.     { Set up the name and its directory in Windows string formats }
  122.     StrPCopy( ThePChar, TheName );
  123.     Dummy := 65535;
  124.     {**** Windows 95 Specialized call ****** }
  125.     TheIcon.Handle := ExtractAssociatedIcon( hInstance , ThePChar , Dummy );
  126.     if TheIcon.Handle = 0 then
  127.     begin
  128.       GetMem( TheOtherPChar , 255 );
  129.       StrPCopy( TheOtherPChar , 'NOICON' );
  130.       TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  131.       FreeMem( TheOtherPChar , 255 );
  132.       exit;
  133.     end;
  134.     FreeMem( ThePChar , 255 );
  135.   end
  136.   else
  137.   { Assume Windows Executable file, so get icon from it with ExtractIcon API }
  138.   begin
  139.     GetMem( ThePChar , 255 );
  140.     StrPCopy( ThePChar , TheName );
  141.     { Try to get first icon for file }
  142.     Dummy := 65535;
  143.     TheIcon.Handle := ExtractAssociatedIcon( hInstance , ThePChar , Dummy );
  144.     FreeMem( ThePChar , 255 );
  145.     { If handle is 0 invalid icon format so use default from RES file }
  146.     if TheIcon.Handle = 0 then
  147.     begin
  148.       GetMem( TheOtherPChar , 255 );
  149.       StrPCopy( TheOtherPChar , 'NOICON' );
  150.       TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  151.       FreeMem( TheOtherPChar , 255 );
  152.       exit;
  153.     end;
  154.   end;
  155. end;
  156.  
  157. { This procedure spaces out the bitbtn components on a tpanel }
  158. procedure SpacePanelButtons( WhichPanel : TPanel );
  159. var TheCalculatedSpacing     ,            { Holds primary spacing }
  160.     TheFullCalculatedSpacing   : Integer; { Holds full spacing    }
  161.     Counter_1                  : Integer; { Loop counter          }
  162.     TotalIBs                   : Integer; { Gets total buttons    }
  163. begin
  164.   { Set up spacing values }
  165.   TotalIBs := WhichPanel.ControlCount;
  166.   TheCalculatedSpacing := (( WhichPanel.Width - 6 - ( TotalIbs * 49 ))
  167.    div ( TotalIbs + 1 ));
  168.   TheFullCalculatedSpacing := TheCalculatedSpacing + 49;
  169.   { Loop through all imported buttons and set their Left values }
  170.   for Counter_1 := 1 to WhichPanel.ControlCount do
  171.   begin
  172.     if Counter_1 = 1 then
  173.     begin
  174.       TBitBtn( WhichPanel.Controls[ Counter_1 - 1 ] ).Left := 3 +
  175.        TheCalculatedSpacing;
  176.     end
  177.     else
  178.     begin
  179.       TBitBtn( WhichPanel.Controls[ Counter_1 - 1 ] ).Left := 3 +
  180.        (( Counter_1 - 1 ) * TheFullCalculatedSpacing ) + TheCalculatedSpacing;
  181.     end;
  182.   end;
  183. end;
  184.  
  185. { This procedure does a fully error-trapped change directory }
  186. procedure TFileWorkBench.ChangeTheDirectory( NewPath : String );
  187. var CurrentDirectory : String;
  188. begin
  189.   if NewPath = '..' then
  190.   begin { Back up one level }
  191.     { Find the current directory }
  192.     GetDir( 0 , CurrentDirectory );
  193.     { Use EFP to move up one level }
  194.     CurrentDirectory := ExtractFilePath( CurrentDirectory );
  195.     { Strip trailing \ if not root }
  196.     CurrentDirectory := StripNonRootTrailingBackSlash( CurrentDirectory );
  197.     { Try the change to the new drive }
  198.     ChDir( CurrentDirectory );
  199.   end
  200.   else
  201.   begin { Change to explicit path }
  202.     { Get target directory path }
  203.     CurrentDirectory := NewPath;
  204.     { Strip trailing \ if not root }
  205.     CurrentDirectory := StripNonRootTrailingBackSlash( CurrentDirectory );
  206.     { Try the change to the new drive }
  207.     ChDir( CurrentDirectory );
  208.   end;
  209. end;
  210.  
  211. { This procedure does a fully error-trapped change directory }
  212. procedure TFileWorkBench.ChangeTheDriveAndDirectory( NewDrive : Integer );
  213. var CurrentDirectory : String;
  214. begin
  215.   { Find the working directory on new drive }
  216.   GetDir( NewDrive , CurrentDirectory );
  217.   { Try the change to the new drive }
  218.   ChDir( CurrentDirectory );
  219. end;
  220.  
  221. { This procedure copies a single file with error trapping }
  222. procedure TFileWorkBench.CopyTheFile( OldPath , NewPath : String );
  223. begin
  224.   { If Copyfile returns false an error occurred }
  225.   CopyFile( OldPath , NewPath + ExtractFileName( OldPath ));
  226. end;
  227.  
  228. { This procedure moves a file by copying and delete it }
  229. procedure TFileWorkBench.MoveTheFile( OldPath , NewPath : String );
  230. var AResult : Boolean; { Internal data flag }
  231. begin
  232.   { If Copyfile returns false an error occurred }
  233.   AResult := CopyFile( OldPath , NewPath +
  234.     ExtractFileName( OldPath ));
  235.   { After valid copying, delete source file }
  236.   if AResult then
  237.   begin
  238.     {***** WIN 95 CHANGE!!! *****}
  239.     SysUtils.DeleteFile( OldPath );
  240.   end;
  241. end;
  242.  
  243. { This procedure safely deletes a single file }
  244. procedure TFileWorkBench.DeleteTheFile( ThePath : String );
  245. begin
  246.   {***** WIN 95 CHANGE!!! *****}
  247.   SysUtils.DeleteFile( ThePath );
  248. end;
  249.  
  250. { This procedure renames a file with full error trapping }
  251. procedure TFileWorkBench.RenameTheFile( OldPath , NewName : String );
  252. begin
  253.   RenameFile( OldPath , NewName );
  254. end;
  255.  
  256. { This procedure creates a new directory with full error trapping }
  257. procedure TFileWorkBench.CreateNewDirectory( NewPath : String );
  258. begin
  259.   Mkdir( NewPath );
  260. end;
  261.  
  262. { This procedure remove a directory with full error trapping }
  263. procedure TFileWorkBench.RemoveDirectory( ThePath : String );
  264. begin
  265.   Rmdir( ThePath );
  266. end;
  267.  
  268. { This is a generic copy routine taken from Delphi sample code }
  269. { It has been edited to return viable error codes!             }
  270. procedure TFileWorkBench.FMXUCopyFile(const FileName, DestName: String);
  271. var
  272.   CopyBuffer: Pointer; { buffer for copying }
  273.   BytesCopied: Longint;
  274.   Source, Dest: Integer; { handles }
  275. const
  276.   ChunkSize: Longint = 8192; { copy in 8K chunks }
  277. begin
  278.   GetMem(CopyBuffer, ChunkSize); { allocate the buffer }
  279.   Source := FileOpen(FileName, fmShareDenyWrite); { open source file }
  280.   if Source < 0 then
  281.   begin  { error creating source file }
  282.     GlobalErrorType := 1;
  283.     GlobalError := -IOResult;
  284.     if GlobalError = 0 then GlobalError := -157;
  285.     FreeMem( CopyBuffer, ChunkSize );
  286.     exit;
  287.   end;
  288.   Dest := FileCreate(DestName); { create output file; overwrite existing }
  289.   if Dest < 0 then
  290.   begin  { error creating destination file }
  291.     FileClose( Source );
  292.     GlobalErrorType := 2;
  293.     GlobalError := -IOResult;
  294.     if GlobalError = 0 then GlobalError := -159;
  295.     FreeMem( CopyBuffer , ChunkSize );
  296.     exit;
  297.   end;
  298.   {$I-}
  299.   repeat
  300.     BytesCopied := FileRead(Source, CopyBuffer^, ChunkSize); { read chunk}
  301.     if BytesCopied > 0 then { if we read anything... }
  302.     FileWrite(Dest, CopyBuffer^, BytesCopied); { ...write chunk }
  303.   until BytesCopied < ChunkSize; { until we run out of chunks }
  304.   {$I+}
  305.   GlobalError := -IOResult;  { get any error code which happens during copying }
  306.   FileClose(Dest); { close the destination file }
  307.   FileClose(Source); { close the source file }
  308.   FreeMem(CopyBuffer, ChunkSize); { free the buffer }
  309. end;
  310.  
  311. { This function calls the sample Copy code and handles errors }
  312. function TFileWorkBench.CopyFile( TargetPath ,
  313.           DestinationPath : String ) : Boolean;
  314. begin
  315.   { Set global error value to no error }
  316.   GlobalError := 0;
  317.   { Call the sample procedure to do the copy }
  318.   FMXUCopyFile( TargetPath, DestinationPath );
  319.   { If no error return true else return false }
  320.   if GlobalError < 0 then CopyFile := false else
  321.    CopyFile := true;
  322. end;
  323.  
  324. { This procedure sets the imported booleans to the file's attributes }
  325. procedure TFileWorkBench.GetFileAttributes( TheFile : String; var IsDirectory ,
  326.            IsArchive , IsVolumeID , IsHidden , IsReadOnly ,
  327.             IsSysFile : Boolean );
  328. var TheResult : Integer; { Traps for error code on VolumeID }
  329. begin
  330.   { Clear the imported flags for default }
  331.   IsDirectory := false;
  332.   IsArchive := false;
  333.   IsVolumeID := false;
  334.   IsHidden := False;
  335.   IsReadOnly := false;
  336.   IsSysFile := false;
  337.   { Make the Dos call }
  338.   TheResult := FileGetAttr( TheFile );
  339.   if TheResult < 0 then
  340.   begin
  341.     { Volume ID returns -2 (?) }
  342.     IsVolumeID := true;
  343.     { It has no other properties }
  344.     exit;
  345.   end;
  346.   { Use AND test to set all other properties }
  347.   if (( TheResult and faDirectory ) = faDirectory ) then IsDirectory := true;
  348.   if (( TheResult and faArchive ) = faArchive ) then IsArchive := true;
  349.   if (( TheResult and faVolumeID ) = faVolumeID ) then IsVolumeID := true;
  350.   if (( TheResult and faReadOnly ) = faReadOnly ) then IsReadOnly := true;
  351.   if (( TheResult and faHidden ) = faHidden ) then IsHidden := true;
  352.   if (( TheResult and faSysFile ) = faSysFile ) then IsSysFile := true;
  353. end;
  354.  
  355. { This function makes sure a pathname has a trailing \ }
  356. function TFileWorkBench.ForceTrailingBackSlash(
  357.           const TheFileName : String ) : String;
  358. var TempString : String;  { Used to hold function result }
  359. begin
  360.   { If no trailing \ add one (root will already have one.) }
  361.   if TheFileName[ Length( TheFileName ) ] <> '\' then
  362.    TempString := TheFileName + '\' else TempString := TheFileName;
  363.   { Return modified or non-modified string }
  364.   ForceTrailingBackslash := TempString;
  365. end;
  366.  
  367. { This function makes sure a non-root dir has no trailing \ }
  368. function TFileWorkBench.StripNonRootTrailingBackSlash(
  369.           const TheFileName : String ) : String;
  370. var TempString : String ; { Used to hold function result }
  371. begin
  372.   { Default is no change }
  373.   TempString := TheFileName;
  374.   { If not root then }
  375.   if Length( TheFileName ) > 3 then
  376.   begin
  377.     { If has a trailing backslash remove it }
  378.     if TheFileName[ Length( TheFileName )] = '\' then
  379.     begin
  380.       TempString := Copy( TheFileName , 1 ,
  381.        Length( TheFileName ) - 1 );
  382.     end;
  383.   end;
  384.   { Export the final result }
  385.   StripNonRootTrailingBackSlash := TempString;
  386. end;
  387.  
  388. { Create method for FIP                                }
  389. constructor TFileIconPanel.Create( AOwner : TComponent );
  390. begin
  391.   { call inherited -- VITAL! }
  392.   inherited Create( AOwner );
  393.   { create icon and label components, making self owner/displayer }
  394.   FTheIcon := TIcon.Create;
  395.   FTheLabel := TLabel.Create( Self );
  396.   FThelabel.Parent := Self;
  397.   { Set own and labels mouse methods to stored methods }
  398.   OnClick := TheClick;
  399.   FTheLabel.OnClick := TheClick;
  400.   { Set alignment and autosize properties of the label }
  401.   FTheLabel.Autosize := false;
  402.   FTheLabel.Alignment := taCenter;
  403.   { Set selected to false }
  404.   Selected := false;
  405. end;
  406.  
  407. { Initialization method for FIP                                         }
  408. procedure TFileIconPanel.Initialize( PanelX              ,
  409.                                      PanelY              ,
  410.                                      PanelWidth          ,
  411.                                      PanelHeight         ,
  412.                                      PanelBevelWidth     ,
  413.                                      LabelFontSize         : Integer;
  414.                                      PanelColor          ,
  415.                                      PanelHighlightColor ,
  416.                                      PanelShadowColor    ,
  417.                                      LabelTextColor        : TColor;
  418.                                      TheFilename         ,
  419.                                      LabelFontName         : String;
  420.                                      LabelFontStyle        : TFontStyles;
  421.                                      ExtraData             : Integer );
  422.  
  423. var TheLabelHeight ,             { Holder for label pixel height }
  424.     TheLabelWidth    : Integer;  { Holder for label pixel width  }
  425.     TheOtherPChar    : PChar;    { Windows ASCIIZ string         }
  426. begin
  427.   { Set the basic properties based on imported parameters }
  428.   Left := PanelX;
  429.   Top := PanelY;
  430.   Width := PanelWidth;
  431.   Height := PanelHeight;
  432.   Color := PanelColor;
  433.   BevelWidth := PanelBevelWidth;
  434.   FHighlightColor := PanelHighlightColor;
  435.   FShadowColor := PanelShadowColor;
  436.   FTheName := TheFilename;
  437.   { If the ExtraData field is non-0 then a drive is being sent in }
  438.   if ExtraData <> 0 then
  439.   begin
  440.     { Use the data field value to determine which icon to get from RES file }
  441.     case ExtraData of
  442.       1 : begin
  443.             GetMem( TheOtherPChar , 255 );
  444.             StrPCopy( TheOtherPChar , 'FLOPPY35' );
  445.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  446.             FreeMem( TheOtherPChar , 255 );
  447.           end;
  448.       2 : begin
  449.             GetMem( TheOtherPChar , 255 );
  450.             StrPCopy( TheOtherPChar , 'FIXEDHD' );
  451.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  452.             FreeMem( TheOtherPChar , 255 );
  453.           end;
  454.       3 : begin
  455.             GetMem( TheOtherPChar , 255 );
  456.             StrPCopy( TheOtherPChar , 'NETWORKHD' );
  457.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  458.             FreeMem( TheOtherPChar , 255 );
  459.           end;
  460.       4 : begin
  461.             GetMem( TheOtherPChar , 255 );
  462.             StrPCopy( TheOtherPChar , 'CDROM' );
  463.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  464.             FreeMem( TheOtherPChar , 255 );
  465.           end;
  466.       5 : begin
  467.             GetMem( TheOtherPChar , 255 );
  468.             StrPCopy( TheOtherPChar , 'RAM' );
  469.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  470.             FreeMem( TheOtherPChar , 255 );
  471.           end;
  472.     end;
  473.     { The FileNme property is already set up for the caption; use directly }
  474.     FTheLabel.Caption := TheFilename;
  475.     { Set up the hint for later use (make sure to set ShowHint) }
  476.     Hint := 'Change to ' + TheFileName;
  477.     ShowHint := true;
  478.     { Set up all imported label properties and center it for drawing }
  479.     with FTheLabel do
  480.     begin
  481.       Font.Name := LabelFontName;
  482.       Font.Size := LabelFontSize;
  483.       Font.Style := LabelFontStyle;
  484.       Font.Color := LabelTextColor;
  485.       Canvas.Brush.Color := PanelColor;
  486.       Canvas.Font := Font;
  487.       TheLabelHeight := Canvas.Textheight( Caption ) + 4;
  488.       TheLabelWidth := Canvas.Textwidth( Caption ) + 4;
  489.       Left := (( Self.Width - TheLabelWidth ) div 2 ) + 1;
  490.       Top := ((( Round( Self.Height * 0.25 ) - 6 ) - TheLabelHeight) div 2) + 1;
  491.       Top := Top + Round( Self.Height * 0.75 );
  492.       Height := TheLabelHeight;
  493.       Width := TheLabelWidth;
  494.     end;
  495.   end
  496.   else
  497.   begin
  498.     { A file or directory has been sent in; use GetIconForFile to obtain an }
  499.     { icon either from the file, its owner, or a RES file default.          }
  500.     GetIconForFile( FTheName , FTheIcon );
  501.     { Check for the Backup caption and set it specially }
  502.     if ExtractfileName( FThename ) = '..' then
  503.     begin
  504.       FTheLabel.Caption := '..';
  505.       Hint := 'Up One Level';
  506.     end
  507.     else
  508.     begin
  509.       { Otherwise just get the filename for the label caption }
  510.       { And the full path for the hint (used later.)          }
  511.       FTheLabel.caption := ExtractFileName( UpperCase( FTheName ));
  512.       Hint := FTheName;
  513.     end;
  514.     { Activate showhint so hints are seen }
  515.     ShowHint := true;
  516.     { Set label properties with imported values and center for display }
  517.     with FTheLabel do
  518.     begin
  519.       Font.Name := LabelFontName;
  520.       Font.Size := LabelFontSize;
  521.       Font.Style := LabelFontStyle;
  522.       Font.Color := LabelTextColor;
  523.       Canvas.Brush.Color := PanelColor;
  524.       Canvas.Font := Font;
  525.       TheLabelHeight := Canvas.Textheight( Caption ) + 4;
  526.       TheLabelWidth := Canvas.Textwidth( Caption ) + 4;
  527.       Left := (( Self.Width - TheLabelWidth ) div 2 ) + 1;
  528.       Top := ((( Round( Self.Height * 0.25 ) - 6 ) - TheLabelHeight) div 2) + 1;
  529.       Top := Top + Round( Self.Height * 0.75 );
  530.       Height := TheLabelHeight;
  531.       Width := TheLabelWidth;
  532.     end;
  533.   end;
  534. end;
  535.  
  536. { Destroy method for FIP }
  537. destructor TFileIconPanel.Destroy;
  538. begin
  539.   { free component resources }
  540.   FTheIcon.Free;
  541.   FTheLabel.Free;
  542.   { call inherited -- VITAL! }
  543.   inherited Destroy;
  544. end;
  545.  
  546. { TheClick method for FIP; used for event responses }
  547. procedure TFileIconPanel.TheClick( Sender : TObject );
  548. begin
  549.   { Currently ignore drive clicks }
  550.   if Pos( 'DRIVE' , FTheName ) > 0 then exit;
  551.   { Flip status of bevels }
  552.   if BevelOuter = bvRaised then BevelOuter := bvLowered else
  553.    BevelOuter := bvRaised;
  554.   { Flip selected variable }
  555.   Selected := not Selected;
  556.   { Set redisplay }
  557.   Invalidate;
  558. end;
  559.  
  560. { Paint method for FIP; overrides normal paint }
  561. procedure TFileIconPanel.Paint;
  562. var
  563.   TheOtherRect   : TRect;   { Holds clientrect   }
  564.   TopColor     ,            { Holds bright color }
  565.   BottomColor    : TColor;  { Holds dark color   }
  566.  
  567. { These methods are from Borland Intl., copyright 1995 }
  568. procedure Frame3D(    Canvas       : TCanvas;
  569.                   var TheRect      : TRect;
  570.                       TopColor   ,
  571.                       BottomColor  : TColor;
  572.                       Width        : Integer );
  573.  
  574. procedure DoRect;
  575. var
  576.   TopRight, BottomLeft: TPoint;
  577. begin
  578.   with Canvas, TheRect do
  579.   begin
  580.     TopRight.X := Right;
  581.     TopRight.Y := Top;
  582.     BottomLeft.X := Left;
  583.     BottomLeft.Y := Bottom;
  584.     Pen.Color := TopColor;
  585.     PolyLine([BottomLeft, TopLeft, TopRight]);
  586.     Pen.Color := BottomColor;
  587.     Dec(BottomLeft.X);
  588.     PolyLine([TopRight, BottomRight, BottomLeft]);
  589.   end;
  590. end;
  591.  
  592. begin
  593.   Canvas.Pen.Width := 1;
  594.   Dec(TheRect.Bottom); Dec(TheRect.Right);
  595.   while Width > 0 do
  596.   begin
  597.     Dec(Width);
  598.     DoRect;
  599.     InflateRect(TheRect, -1, -1);
  600.   end;
  601.   Inc(TheRect.Bottom); Inc(TheRect.Right);
  602. end;
  603.  
  604. procedure AdjustColors(Bevel: TPanelBevel);
  605. begin
  606.   TopColor := FHighlightColor;
  607.   if Bevel = bvLowered then TopColor := FShadowColor;
  608.   BottomColor := FShadowColor;
  609.   if Bevel = bvLowered then BottomColor := FHighlightColor;
  610. end;
  611.  
  612. { Custom code begins here }
  613. begin
  614.   { Get the rectangle of the control with API/method call }
  615.   TheOtherRect := GetClientRect;
  616.   { draw basic rectangle with basic color }
  617.   with Canvas do
  618.   begin
  619.     Brush.Color := Color;
  620.     FillRect(TheOtherRect);
  621.   end;
  622.   { Set up for top "icon" frame  and draw it with frame3d }
  623.   TheOtherRect.Right := Width;
  624.   TheOtherRect.Bottom := Round( Height * 0.75 ) - 6 ;
  625.   if BevelOuter <> bvNone then
  626.   begin
  627.     AdjustColors(BevelOuter);
  628.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  629.   end;
  630.   Frame3D(Canvas, TheOtherRect, Color, Color, BorderWidth);
  631.   if BevelInner <> bvNone then
  632.   begin
  633.     AdjustColors(BevelInner);
  634.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  635.   end;
  636.   { Do the same for the lower "label" frame }
  637.   TheOtherRect.Top := Round( Height * 0.75 ) - 5;
  638.   TheOtherRect.Left := 0;
  639.   TheOtherRect.Bottom := Height;
  640.   TheOtherRect.Right := Width;
  641.   if BevelOuter <> bvNone then
  642.   begin
  643.     AdjustColors(BevelOuter);
  644.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  645.   end;
  646.   Frame3D(Canvas, TheOtherRect, Color, Color, BorderWidth);
  647.   if BevelInner <> bvNone then
  648.   begin
  649.     AdjustColors(BevelInner);
  650.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  651.   end;
  652.   { Then draw the icon using canvas draw method }
  653.   Canvas.Draw( (( Width - 32 ) div 2 ) + 1 ,
  654.   ((( Round( Height * 0.75 ) - 6 ) - 32 ) div 2 ) + 1 , FTheIcon );
  655. end;
  656.  
  657. { This procedure clears a scrollbox of all FileIconPanels }
  658. procedure TFileIconPanelScrollbox.ClearTheFIPs;
  659. var TheComponent : TComponent;
  660. begin
  661.   { Note that must use while loop since component count continually }
  662.   { decreases as removes are made!                                  }
  663.   while ComponentCount > 0 do
  664.   begin
  665.     { Save the component as a generic TComponent }
  666.     TheComponent := Components[ 0 ];
  667.     { Call removecomponent to pull it out of the owner list for sb }
  668.     { This avoids GPF when freeing the sb.                         }
  669.     RemoveComponent( Components[ 0 ]);
  670.     { Typecast the pointer and free it to release memory and res. }
  671.     TFileIconPanel( TheComponent ).Free;
  672.   end;
  673. end;
  674.  
  675. { This procedure scans for drives and obtains their type and creates file }
  676. { icon panels to represent them.                                          }
  677. procedure TFileIconPanelScrollBox.AddDriveIcons( var XCounter ,
  678.            YCounter : Integer );
  679. type
  680.   { This if from filectrl unit; reproduce here for completeness }
  681.   TDriveType = (dtUnknown, dtNoDrive, dtFloppy, dtFixed, dtNetwork, dtCDROM,
  682.                 dtRAM);
  683. var
  684.   DrivePC         : array[0..256] of char;
  685.   DriveNum        : Integer;         { Used to get next drive via DOS fn   }
  686.   IconType        : Integer;         { Used to hold icon type (defacto dt) }
  687.   DriveChar       : Char;            { Used to hold drive letter           }
  688.   DriveType       : TDriveType;      { Used for set-valued drive type      }
  689.   Finished        : Boolean;         { Loop flag                           }
  690.   TheFIP          : TFileIconPanel;  { Generic FileIconPanel variable      }
  691.   ButtonColor   ,                    { Main panel color                    }
  692.   ButtonHLColor ,                    { Bright panel color                  }
  693.   ButtonSColor  ,                    { Dark panel color                    }
  694.   Textcolor       : TColor;          { Label text color                    }
  695.  
  696. (*============================REMOVED DUE TO WINDOWS 95==================
  697. { This code is from the FileCtrl Unit; copyright Borland Intl 1995      }
  698. { Check whether drive is a CD-ROM.  Returns True if MSCDEX is installed }
  699. {  and the drive is using a CD driver                                   }
  700.  
  701. function IsCDROM(DriveNum: Integer): Boolean; assembler;
  702. asm
  703.   MOV   AX,1500h { look for MSCDEX }
  704.   XOR   BX,BX
  705.   INT   2fh
  706.   OR    BX,BX
  707.   JZ    @Finish
  708.   MOV   AX,150Bh { check for using CD driver }
  709.   MOV   CX,DriveNum
  710.   INT   2fh
  711.   OR    AX,AX
  712.   @Finish:
  713. end;
  714.  
  715. { This code is from the FileCtrl Unit; copyright Borland Intl 1995      }
  716. { Check whether drive is a RAM drive.                                   }
  717. function IsRAMDrive(DriveNum: Integer): Boolean; assembler;
  718. var
  719.   TempResult: Boolean;
  720. asm
  721.   MOV   TempResult,False
  722.   PUSH  DS
  723.   MOV   BX,SS
  724.   MOV   DS,BX
  725.   SUB   SP,0200h
  726.   MOV   BX,SP
  727.   MOV   AX,DriveNum
  728.   MOV   CX,1
  729.   XOR   DX,DX
  730.   INT   25h  { read boot sector }
  731.   ADD   SP,2
  732.   JC    @ItsNot
  733.   MOV   BX,SP
  734.   CMP   BYTE PTR SS:[BX+15h],0F8h  { reverify fixed disk }
  735.   JNE   @ItsNot
  736.   CMP   BYTE PTR SS:[BX+10h],1  { check for single FAT }
  737.   JNE   @ItsNot
  738.   MOV   TempResult,True
  739.   @ItsNot:
  740.   ADD   SP,0200h
  741.   POP   DS
  742.   MOV   AL, TempResult
  743. end;
  744.  
  745. { This code is from the FileCtrl Unit; copyright Borland Intl 1995      }
  746. { Finds the type of a drive letter.                                     }
  747. function FindDriveType(DriveNum: Integer): TDriveType;
  748. begin
  749.   Result := TDriveType(GetDriveType(DriveNum));
  750.   if (Result = dtFixed) or (Result = dtNetwork) then
  751.   begin
  752.     if IsCDROM(DriveNum) then Result := dtCDROM
  753.     else if (Result = dtFixed) then
  754.     begin
  755.         { do not check for RAMDrive under Windows NT }
  756.       if ((GetWinFlags and $4000) = 0) and IsRAMDrive(DriveNum) then
  757.         Result := dtRAM;
  758.     end;
  759.   end;
  760. end;
  761. ==================END REMOVAL FOR WINDOWS 95===========================*)
  762.  
  763. begin
  764.   { Set the button colors to an aquamarine color scheme for drives }
  765.   ButtonColor := clTeal;
  766.   ButtonHLColor := clAqua;
  767.   ButtonSColor := clNavy;
  768.   TextColor := clblack;
  769.   { Set initial variables before looping for all drives }
  770.   finished := false;
  771.   DriveNum := 0;
  772.   while not finished do
  773.   begin
  774.     { Start with no drive found }
  775.     IconType := 0;
  776.     { Set its letter and make it uppercase }
  777.     DriveChar := Chr(DriveNum + ord('a'));
  778.     DriveChar := Upcase(DriveChar);
  779.     StrPCopy( DrivePC , DriveChar + ':\' );
  780.     {*&&&&&&&&&&&&&&&  WIN 95 CALL  &&&&&&&&&&&&&&&&&&&*}
  781.     DriveType := TDriveType(GetDriveType( DrivePC ));
  782.     { Assign an icon based on the drive type; if no drive exists type is nil }
  783.     case DriveType of
  784.       dtFloppy  : IconType := 1;
  785.       dtFixed   : IconType := 2;
  786.       dtNetwork : IconType := 3;
  787.       dtCDROM   : IconType := 4;
  788.       dtRAM     : IconType := 5;
  789.     end;
  790.     { Set to check next drive letter }
  791.     DriveNum := DriveNum + 1;
  792.     { But if no match then out of drives so set exit flag }
  793.     if IconType = 0 then finished := true;
  794.     { If drive was valid then set up the new FileIconPanel on the imported }
  795.     { Scrollbox                                                            }
  796.     if not finished then
  797.     begin
  798.       { Create the FileIconPanel and set its parent for memory mgmt and display}
  799.       TheFIP := TFileIconPanel.Create( Self );
  800.       TheFIP.Parent := Self;
  801.       { Call its initialize method with imported position values and the   }
  802.       { preset color scheme, a drive caption, and a minimum font. Note the }
  803.       { setting of the ExtraData field to non-zero; this signals a drive   }
  804.       { rather than a file being sent in.                                  }
  805.       TheFIP.Initialize((( XCounter - 1 ) * TheIconSpacing ),
  806.        (( YCounter - 1  ) * TheIconSpacing ) , TheIconSize , TheIconSize , 3 ,
  807.         7 , ButtonColor, ButtonHLColor,
  808.        ButtonSColor , TextColor , 'DRIVE ' + DriveChar + ':' , 'MS Serif' , [] ,
  809.        IconType );
  810.       { Increment the column counter; if it exceeds max move to new row      }
  811.       { Note that these are 'var' parameters and will export final position. }
  812.       XCounter := XCounter + 1;
  813.       if XCounter > MaxIconsInARow then
  814.       begin
  815.         XCounter := 1;
  816.         YCounter := YCounter + 1;
  817.       end;
  818.     end;
  819.   end;
  820. end;
  821.  
  822. { This procedure assigns colors to FIP's based on file attributes }
  823. procedure TFileIconPanelScrollBox.GetColorsForFileIcon( TheFile : String;
  824.            var BC , HC , SC , TC : TColor );
  825. var AmADir      ,             { Booleans hold file attribs }
  826.     AmAnArchive ,
  827.     AmAVolumeId ,
  828.     AmHidden    ,
  829.     AmReadOnly  ,
  830.     AmSystem      : Boolean;
  831. begin
  832.   { Make the call to internal fileworkbench to set attributes }
  833.   TheFWB.GetFileAttributes( TheFile , AmADir , AmAnArchive , AmAVolumeId ,
  834.    AmHidden , AmReadOnly , AmSystem );
  835.   { Volume ID has no subtypes }
  836.   if AmAVolumeID then
  837.   begin
  838.     BC := clOlive;
  839.     HC := clYellow;
  840.     SC := clBlack;
  841.     TC := clWhite;
  842.     exit;
  843.   end;
  844.   { Check all directory combinations }
  845.   if AmADir then
  846.   begin
  847.     BC := clNavy;
  848.     HC := clBlue;
  849.     SC := clBlack;
  850.     TC := clWhite;
  851.     if AmHidden then
  852.     begin
  853.       if AmReadOnly then
  854.       begin
  855.         if AmSystem then
  856.         begin { One HECK of a file! }
  857.           BC := clBlack;
  858.           HC := clSilver;
  859.           SC := clGray;
  860.           TC := clWhite;
  861.         end
  862.         else
  863.         begin { Dir,RO,Hid }
  864.           BC := clMaroon;
  865.           HC := clFuchsia;
  866.           SC := clGreen;
  867.           TC := clWhite;
  868.         end;
  869.       end
  870.       else
  871.       begin { Dir,Hid }
  872.         BC := clPurple;
  873.         HC := clFuchsia;
  874.         SC := clBlack;
  875.         TC := clWhite;
  876.       end;
  877.     end
  878.     else
  879.     begin
  880.       if AmReadOnly then
  881.       begin
  882.         if AmSystem then
  883.         begin { Dir,RO,Sys }
  884.           BC := clMaroon;
  885.           HC := clLime;
  886.           SC := clGreen;
  887.           TC := clWhite;
  888.         end
  889.         else
  890.         begin { Dir,RO }
  891.           BC := clGreen;
  892.           HC := clLime;
  893.           SC := clBlack;
  894.           TC := clWhite;
  895.         end;
  896.       end
  897.       else
  898.       begin
  899.         if AmSystem then
  900.         begin { Dir,Sys }
  901.           BC := clMaroon;
  902.           HC := clRed;
  903.           SC := clBlack;
  904.           TC := clWhite;
  905.         end;
  906.       end;
  907.     end;
  908.   end
  909.   else { Archive Only; check all combinations }
  910.   begin
  911.     BC := clSilver;
  912.     HC := clWhite;
  913.     SC := clGray;
  914.     TC := clBlack;
  915.     if AmHidden then
  916.     begin
  917.       if AmReadOnly then
  918.       begin
  919.         if AmSystem then
  920.         begin { Hid,RO,Sys }
  921.           BC := clRed;
  922.           HC := clLime;
  923.           SC := clPurple;
  924.           TC := clBlack;
  925.         end
  926.         else
  927.         begin { RO,Hid }
  928.           BC := clLime;
  929.           HC := clFuchsia;
  930.           SC := clMaroon;
  931.           TC := clBlack;
  932.         end;
  933.       end
  934.       else
  935.       begin { Hid }
  936.         BC := clFuchsia;
  937.         HC := clWhite;
  938.         SC := clPurple;
  939.         TC := clBlack;
  940.       end;
  941.     end
  942.     else
  943.     begin
  944.       if AmReadOnly then
  945.       begin
  946.         if AmSystem then
  947.         begin { RO,Sys }
  948.           BC := clRed;
  949.           HC := clLime;
  950.           SC := clMaroon;
  951.           TC := clBlack;
  952.         end
  953.         else
  954.         begin { RO }
  955.           BC := clLime;
  956.           HC := clWhite;
  957.           SC := clGreen;
  958.           TC := clBlack;
  959.         end;
  960.       end
  961.       else
  962.       begin
  963.         if AmSystem then
  964.         begin { System }
  965.           BC := clRed;
  966.           HC := clWhite;
  967.           SC := clMaroon;
  968.           TC := clBlack;
  969.         end;
  970.       end;
  971.     end;
  972.   end;
  973. end;
  974.  
  975. { This procedure gets all icons for an given directory, including drives and }
  976. { standard subdirectories. It does not get special combinations or h/ro/sys  }
  977. procedure TFileIconPanelScrollbox.GetIconsForEntireDirectory(
  978.             TargetPath  : String );
  979. var Finished        : Boolean;         { Loop flag              }
  980.     TheSR           : TSearchRec;      { Searchrecord for FF/FN }
  981.     TheResult       : Integer;         { return variable        }
  982.     TempPath        : String;          { path for FF/FN         }
  983.     TheFIP          : TFileIconPanel;  { generic FIP holder     }
  984.     RowCounter    ,                    { position in row of FIP }
  985.     ColumnCounter   : Integer;         { position in col of FIP }
  986.     ButtonColor   ,                    { main panel color       }
  987.     ButtonHLColor ,                    { bright panel color     }
  988.     ButtonSColor  ,                    { dark panel color       }
  989.     Textcolor       : TColor;          { label text color       }
  990.     IsADir ,                           { Variable for file attr }
  991.     IsAnArchive ,
  992.     IsAVolumeID,
  993.     IsAReadOnlyFile,
  994.     IsAHiddenFile ,
  995.     IsASystemFile     : Boolean;
  996.     MaxTextLength     : Integer;       { Used to safely set size}
  997. begin
  998.   { hide during refresh }
  999.   Visible := false;
  1000.   { Delete the current set, if any }
  1001.   ClearTheFIPs;
  1002.   { Get the icon sizes }
  1003.   TheFIP := TFileIconPanel.Create( Self );
  1004.   TheFIP.Parent := Self;
  1005.   TheFIP.FTheLabel.Canvas.Font.Name := 'MS Serif';
  1006.   TheFIP.FTheLabel.Canvas.Font.Size := 7;
  1007.   MaxTextLength := TheFIP.FTheLabel.Canvas.TextWidth( 'COMMAND.COM' );
  1008.   TheFIP.Free;
  1009.   TheIconSize := MaxTextLength + 13;
  1010.   TheIconSpacing := TheIconSize + 5;
  1011.   { Set up maximum icons per row based on screen size }
  1012.   MaxIconsInARow := ( Screen.Width div TheIconSpacing );
  1013.   { Set up the position counters }
  1014.   RowCounter := 1;
  1015.   ColumnCounter := 1;
  1016.   { Get the drives for the current machine }
  1017.   AddDriveIcons( ColumnCounter , RowCounter  );
  1018.   { Set up the initial variables }
  1019.   Finished := false;
  1020.   TempPath := TargetPath + '*.*';
  1021.   { Make the call to FindFirst set to get any file; will return '.' }
  1022.   { so discard it.                                                  }
  1023.   FindFirst( TempPath , faAnyFile , TheSR );
  1024.   { loop through all files in the directory and look for directories }
  1025.   while not Finished do
  1026.   begin
  1027.     { Make call to FindNext, using only SearchRecord from FindFirst }
  1028.     TheResult := FindNext( TheSR );
  1029.     { A 18 result means no more files so exit }
  1030.     {******  WINDOWS 95 INTRODUCES BUG!!! ******}
  1031.     {if TheResult < 0 then finished := true else}
  1032.     if TheResult <> 0 then finished := true else
  1033.     begin
  1034.       { Otherwise check for a directory attribute }
  1035.       if (( FileGetAttr( TargetPath + TheSR.Name ) and faDirectory ) =
  1036.        faDirectory ) then
  1037.       begin
  1038.         GetColorsForFileIcon( TargetPath + TheSR.Name , ButtonColor ,
  1039.          ButtonHLColor , ButtonSColor , TextColor );
  1040.         { If found create a new FileIconPanel on the imported scrollbox }
  1041.         { Note sending 0 ExtraData parameter to indicate file not drive }
  1042.         TheFIP := TFileIconPanel.Create( Self );
  1043.         TheFIP.Parent := Self;
  1044.         TheFIP.Initialize((( ColumnCounter - 1 ) * TheIconSpacing ),
  1045.          (( RowCounter - 1  ) * TheIconSpacing ) , TheIconSize, TheIconSize ,
  1046.           3 , 7 , ButtonColor, ButtonHLColor , ButtonSColor , TextColor ,
  1047.            TargetPath + TheSr.Name , 'MS Serif' , [] , 0 );
  1048.         { Increment column counter and move to new row if past limit }
  1049.         ColumnCounter := ColumnCounter + 1;
  1050.         if ColumnCounter > MaxIconsInARow then
  1051.         begin
  1052.           ColumnCounter := 1;
  1053.           RowCounter := RowCounter + 1;
  1054.         end;
  1055.       end;
  1056.     end;
  1057.   end;
  1058.   { Set up new initialization variables }
  1059.   Finished := false;
  1060.   TempPath := TargetPath + '*.*';
  1061.   { Make needed call to FindFirst and discard '.' }
  1062.   FindFirst( TempPath , faAnyFile , TheSR );
  1063.   while not Finished do
  1064.   begin
  1065.     { Loop through file again, this time getting only archive files }
  1066.     TheResult := FindNext( TheSR );
  1067.     {******  WINDOWS 95 INTRODUCES BUG!!! ******}
  1068.     {if TheResult < 0 then finished := true else}
  1069.     { Result of 18 indicates no more files      }
  1070.     if TheResult <> 0 then Finished := true else
  1071.     begin
  1072.       { If faArchive file then add new FileIconPanel }
  1073.       TheFWB.GetFileAttributes(( Targetpath + TheSR.Name ) , IsADir ,
  1074.        IsAnArchive , IsAVolumeId , IsAHiddenFile , IsAReadOnlyFile ,
  1075.         IsASystemFile );
  1076.       if (( IsAnArchive ) and ( not IsADir )) then
  1077.       begin
  1078.         GetColorsForFileIcon( TargetPath + TheSR.Name , ButtonColor ,
  1079.          ButtonHLColor , ButtonSColor , TextColor );
  1080.         { Initialize new FileIconPanel and call initialize, sending 0 ED }
  1081.         TheFIP := TFileIconPanel.Create( Self );
  1082.         TheFIP.Parent := Self;
  1083.         TheFIP.Initialize((( ColumnCounter - 1 ) * TheIconSpacing ),
  1084.          (( RowCounter - 1  ) * TheIconSpacing ) , TheIconSize , TheIconSize ,
  1085.           3 , 7 , ButtonColor, ButtonHLColor , ButtonSColor , TextColor ,
  1086.            TargetPath + TheSr.Name , 'MS Serif' , [] , 0 );
  1087.         { Increment column counter and if needed row counter }
  1088.         ColumnCounter := ColumnCounter + 1;
  1089.         if ColumnCounter > MaxIconsInARow then
  1090.         begin
  1091.           ColumnCounter := 1;
  1092.           RowCounter := RowCounter + 1;
  1093.         end;
  1094.       end;
  1095.     end;
  1096.   end;
  1097.   { Reset to visible }
  1098.   Visible := true;
  1099. end;
  1100.  
  1101. { Update method for FIPscrollbox }
  1102. procedure TFileIconPanelScrollBox.Update;
  1103. begin
  1104.   IconsNeedRefreshing := true;
  1105.   { Force a repaint }
  1106.   InvalidateRect( TheStoredHandle , nil , true );
  1107. end;
  1108.  
  1109. { Create method for FIPScrollbox }
  1110. constructor TFileIconPanelScrollBox.Create( AOwner : TComponent );
  1111. begin
  1112.   inherited Create( AOwner );
  1113.   TheFWB := TFileWorkBench.Create( Self );
  1114. end;
  1115.  
  1116. { This function returns the next selected file's name }
  1117. function TFileIconPanelScrollBox.GetNextSelection( SourceDirectory : String;
  1118.                            var CurrentItem : Integer ) : String;
  1119. var TheResult    : String;      { Holds result of function }
  1120.     TheComponent : TComponent;  { Used for typecast        }
  1121.     finished     : boolean;     { Loop control variable    }
  1122.     TheComponentCount : Integer;
  1123. begin
  1124.   TheComponentCount := ComponentCount;
  1125.   { If past end of components exit with no result }
  1126.   if CurrentItem > TheComponentCount then TheResult := '' else
  1127.   begin
  1128.     { Set loop counter and run till find match or run out }
  1129.     finished := false;
  1130.     while not finished do
  1131.     begin
  1132.       { Pull component out of the list and check it }
  1133.       TheComponent := Components[ CurrentItem - 1 ];
  1134.       { Increment counter for later }
  1135.       CurrentItem := CurrentItem + 1;
  1136.       { Do the typecast with AS }
  1137.       with TheComponent as TFileIconPanel do
  1138.       begin
  1139.         { If its selected make sure OK }
  1140.         if Selected then
  1141.         begin
  1142.           { Don't accept backup for this level of operation }
  1143.           if FTheLabel.Caption <> '..' then
  1144.           begin
  1145.             { Otherwise return the name and abort the loop }
  1146.             TheResult := FTheName;
  1147.             finished := true;
  1148.           end;
  1149.         end
  1150.         else
  1151.         begin
  1152.           { Check to see if out of components }
  1153.           if CurrentItem > TheComponentCount then
  1154.           begin
  1155.             { If so signal error and abort }
  1156.             TheResult := '';
  1157.             finished := true;
  1158.           end;
  1159.         end;
  1160.       end;
  1161.     end;
  1162.   end;
  1163.   GetNextSelection := TheResult;
  1164. end;
  1165.  
  1166. end.
  1167.